package main.java.DMDE.view;

import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.jgoodies.forms.factories.CC;
import com.jgoodies.forms.layout.FormLayout;

import main.java.DMDE.controllers.IParameterController;
import main.java.DMDE.infrastructure.visual.OperationNode;
import main.java.DMDE.infrastructure.visual.ParameterNode;
import main.java.DMDE.model.Parameter;
import main.java.DMDE.model.Type;


public class ParameterView implements IParameterView {

    private IParameterController paramController;
    private JList<ParameterNode> paramModelList;
    private DefaultListModel<ParameterNode> paramModel;
    private Parameter paramSelected;

    private JFrame frame;
    private JLabel nameText;
    private JTextField name;
    private JLabel typeText;
    private JTextField type;
    private JButton addButton;
    private JButton removeButton;
    private JButton editButton;
    private JButton finishButton;
    private JScrollPane scrollPane;
    private List<Parameter> parameters;

    public ParameterView() {
	parameters = new ArrayList<Parameter>();
	initComponentsPanel();
	initList();
	initButtons();
    }

    private void initButtons() {
	addButton.addActionListener(new ActionListener() {
	    @Override
	    public void actionPerformed(ActionEvent actionEvent) {
		create();
	    }

	});

	editButton.addActionListener(new ActionListener() {
	    @Override
	    public void actionPerformed(ActionEvent e) {
		edit();
	    }
	});

	removeButton.addActionListener(new ActionListener() {
	    @Override
	    public void actionPerformed(ActionEvent e) {
		remove();
	    }
	});
	
	finishButton.addActionListener(new ActionListener() {
	    @Override
	    public void actionPerformed(ActionEvent e) {
		finish();
	    }
	});
	cleanView();

    }

    private void cleanView() {
	name.setText("");
	type.setText("");
	paramModelList.revalidate();
	paramModelList.repaint();
	paramModelList.updateUI();
	paramModelList.clearSelection();
    }

    private void create() {
	if (this.name.getText().equals("")) {
	    this.showNameError();
	} else {
	    Parameter paramCreated = paramController.addParameter();
	    if (paramCreated != null) {
		paramModel.addElement(new ParameterNode(paramCreated));
		cleanView();
	    }
	}

    }

    private void showNameError() {
	JOptionPane.showMessageDialog(null, "Parameters should have a name");
    }

    private void edit() {
	if (paramSelected != null) {
	    Parameter param = this.paramController.editParameter(paramSelected);
	    if (param != null) {
		paramSelected = null;
		cleanView();
	    } else
		showNameError();
	}
    }

    private void remove() {
	ParameterNode node = paramModelList.getSelectedValue();
	if (node != null) {
	    if (parameters.remove(node.getParameter())) {
		paramModel.removeElement(node);
		paramSelected = null;
		cleanView();
	    }
	}
    }
    
    private void finish() {
	this.frame.setVisible(false);
	loadParameters();
    }

    private void initList() {
	this.paramModelList = new JList<ParameterNode>();
	scrollPane.setViewportView(paramModelList);
	paramModel = new DefaultListModel<ParameterNode>();
	paramModelList.setModel(paramModel);
	this.paramSelected = null;
	paramModelList.addListSelectionListener(new ListSelectionListener() {

	    @Override
	    public void valueChanged(ListSelectionEvent e) {
		if (!e.getValueIsAdjusting()) {
		    if (paramModelList.getSelectedValue() instanceof ParameterNode) {
			Parameter paramSelected = ((ParameterNode) paramModelList
				.getSelectedValue()).getParameter();
			parameterSelected(paramSelected);
		    } else {
			paramSelected = null;
		    }
		}
	    }
	});

	paramModelList.addKeyListener(new KeyListener() {

	    @Override
	    public void keyPressed(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_DELETE) {
		    if (paramModelList.getSelectedValue() instanceof ParameterNode) {
			// paramNode paramNode =
			// (paramNode)paramModelList.getSelectedValue();
			// TODO:terminar
			// paramModel.removeNode((paramNode)paramModelList.getSelectedValue());
			cleanView();
		    }
		}

	    }

	    @Override
	    public void keyReleased(KeyEvent arg0) {

	    }

	    @Override
	    public void keyTyped(KeyEvent arg0) {

	    }
	});

    }

    private void parameterSelected(Parameter paramSelected) {
	if (paramSelected != null) {
	    this.paramSelected = paramSelected;
	    this.name.setText(paramSelected.getName());
	    this.type.setText(paramSelected.getType().getName());
	}
    }

    private void initComponentsPanel() {
	frame = new JFrame();
	Container panel = frame.getContentPane();
	frame.setTitle("Parameter");
	nameText = new JLabel();
	name = new JTextField();
	typeText = new JLabel();
	type = new JTextField();
	nameText.setText("Name: ");
	nameText.setLabelFor(name);
	typeText.setText("Type: ");
	typeText.setLabelFor(type);
	addButton = new JButton();
	removeButton = new JButton();
	editButton = new JButton();
	finishButton = new JButton();
	scrollPane = new JScrollPane();

	panel.setLayout(new FormLayout(
		"4dlu,70dlu,8dlu,pref,4dlu,pref,4dlu,pref,fill:4dlu:grow",
		"4dlu,pref,20dlu,pref,20dlu,pref,4dlu,pref,fill:4dlu:grow"));

	panel.add(scrollPane, CC.xywh(2, 2, 1, 4));

	addButton.setText("Add");
	panel.add(addButton, CC.xy(4, 6));

	editButton.setText("Edit");
	panel.add(editButton, CC.xy(6, 6));

	removeButton.setText("Remove");
	panel.add(removeButton, CC.xy(8, 6));
	
	finishButton.setText("Finish");
	panel.add(finishButton,CC.xy(8, 8));

	panel.add(typeText, CC.xy(4, 2));
	panel.add(type, CC.xyw(6, 2, 3));
	panel.add(nameText, CC.xy(4, 4));
	panel.add(name, CC.xyw(6, 4, 3));

	frame.pack();
	frame.setLocationRelativeTo(frame.getOwner());
    }

    @Override
    public JFrame getFrame() {
	return this.frame;
    }

    @Override
    public String getName() {
	return this.name.getText();
    }

    @Override
    public Type getType() {
	return new Type(this.type.getText());
    }

    @Override
    public void setController(IParameterController paramController) {
	this.paramController = paramController;
    }

    private void loadParameters(){
	parameters.removeAll(parameters);
	 for(int i = 0; i < paramModel.getSize(); i++) {
	     parameters.add(paramModel.getElementAt(i).getParameter());
	 }
    }

    @Override
    public List<Parameter> getParameters() {
	return parameters;
    }

    @Override
    public void setParameters(List<Parameter> parameters) {
	this.parameters = parameters;
	for(Parameter param: parameters){
	    paramModel.addElement(new ParameterNode(param));
	}
    }

}
